package jam4j.lang;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;

import jam4j.Globals;
import jam4j.Jam4J;
import jam4j.JamDateFormat;
import jam4j.OperatingSystem;
import jam4j.Platform;

/**
 * Any of the special variables with built-in semantics. See the Perforce Jam
 * documentation for details.
 * 
 * @author Luke Maurer
 */
public enum SpecialVariable {
    SEARCH(true),
    LOCATE(true),
    HDRSCAN(true),
    HDRRULE(true),
    OS {
        public String[] initialValue() {
            return new String[] { OperatingSystem.hostSystem().toString() };
        } 
    },
    OSPLAT {
        public String[] initialValue() {
            final Platform platform = Platform.hostPlatform();
            return platform == null ? null : 
                    new String[] { platform.toString() };
        }
    },
    MAC,
    NT,
    OS2,
    UNIX,
    VMS,
    JAMDATE {
        public String[] initialValue() {
            final Date date = Globals.startupTime();
            return new String[] { new JamDateFormat().format(date) };
        }
    },
    JAMUNAME {
        private String uname(char option) throws IOException {
            final Process process =
                new ProcessBuilder("uname", "-" + option)
                    .redirectErrorStream(true)
                    .start();
            
            process.getOutputStream().close(); // close the child stdin
            
            final InputStreamReader reader =
                new InputStreamReader(process.getInputStream());
            final char[] buf = new char[1024];
            final StringBuilder builder = new StringBuilder();
            while (true) {
                final int read;
                if ((read = reader.read(buf)) == -1)
                    break;
                builder.append(buf, 0, read);
            }
            
            return builder.toString().trim();
        }
        
        public String[] initialValue() {
            try {
                return new String[] {
                    uname('m'),
                    uname('v'),
                    uname('r'),
                    uname('n'),
                    uname('s'),
                };
            } catch (IOException e) {
                return null;
            }
        }
    },
    JAMVERSION {
        public String[] initialValue() {
            return new String[] { 
                Jam4J.VERSION + 
                    ". OS=" + OperatingSystem.hostSystem() + 
                    ". " + Jam4J.COPYRIGHT
            };
        }
    },
    JAMSHELL {
        public String[] initialValue() {
            return OperatingSystem.hostSystem() == OperatingSystem.NT ?
                    new String[] { "cmd.exe", "/Q/C" } :
                    new String[] { "/bin/sh", "-c" };
        }
    }
    ;
    
    private final boolean initiallyUnset;
    private SpecialVariable(boolean initiallyUnset) {
        this.initiallyUnset = initiallyUnset;
    }
    private SpecialVariable() {
        this(false);
    }
    
    private static final String[] TRUE = { "true" };
    
    public String[] initialValue() {
        return !initiallyUnset && 
                name().equals(OperatingSystem.hostSystem().flagName()) ?
                        TRUE : null;
    }
    
    public final String[] get(Context cxt) {
        return cxt.get(this.toString());
    }
}
